//
//  CHImageAdditions.m
//  ImageExport
//
//  Created by Jelle De Laender & Pieter Omvlee on 30/01/07.
//  Copyright 2007 GetDrawIt. All rights reserved.
//

#import "CHImageAdditions.h"

/* Create a CGImageSourceRef from raw data */
CGImageRef CreateCGImageFromData(NSData* data)
{
  CGImageRef imageRef = NULL;
  CGImageSourceRef sourceRef;
  
  sourceRef = CGImageSourceCreateWithData((CFDataRef)data, NULL);
  if (sourceRef) {
    imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, NULL);
    CFRelease(sourceRef);
  }
  
  return imageRef;
}

/* Create a CGImageSourceRef from a file */
CGImageRef CreateCGImageFromFile(NSString* path)
{
  NSURL* url          = [NSURL fileURLWithPath:path];
  CGImageRef imageRef = NULL;
  CGImageSourceRef sourceRef;
  
  sourceRef = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
  if (sourceRef) {
    imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, NULL);
    CFRelease(sourceRef);
  }
  
  return imageRef;
}

@implementation NSImage (CHImageAdditions)

//clipping an image
- (NSImage *)imageByCroppingToRect:(NSRect)r
{
  NSImage *result = [[[NSImage alloc] initWithSize:r.size] autorelease];
  [result lockFocus];
  [self drawInRect:CHRectFromSize(r.size) fromRect:r operation:NSCompositeSourceOver fraction:1.0];
  [result unlockFocus];
  
  return result;
}

- (NSImage *)imageByResizingToSize:(NSSize)s
{
  if (!NSEqualSizes(s, [self size])) {
    NSImage *result = [[NSImage alloc] initWithSize:s];
    [result lockFocus];
    [[NSGraphicsContext currentContext] setShouldAntialias:YES];
    [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
    [self drawInRect:CHRectFromSize(s) fromRect:CHRectFromSize([self size]) operation:NSCompositeSourceOver fraction:1.0];
    [result unlockFocus];
    return [result autorelease];
  } else
    return [[self copy] autorelease];
}

/* Load an Image from data (with dpi etc) */
+ (id)imageFromPath:(NSString *)path {
  if ([[path pathExtension] isEqualTo:@"pdf"] || [[path pathExtension] isEqualToString:@"eps"] || [[path pathExtension] isEqualToString:@"psd"])
    return [[[NSImage alloc] initWithContentsOfFile:path] autorelease];
  return [self imageFromCGImageRef:CreateCGImageFromFile(path)];
}

+ (id)imageFromData:(NSData *)data type:(NSString *)type {
  if ([type isEqualToString:@"FotoPDF"] || [type isEqualToString:@"FotoGIF"] || [type isEqualToString:@"FotoEPS"] || [type isEqualToString:@"FotoPSD"]) {
    return [[[NSImage alloc] initWithData:data] autorelease];
  } else
    return [self imageFromCGImageRef:CreateCGImageFromData(data)];
}

+ (id)imageFromCGImageRef:(CGImageRef)image
{
  NSRect imageRect = NSMakeRect(0.0, 0.0, 0.0, 0.0);
  CGContextRef imageContext = nil;
  NSImage* newImage = nil;
  
  // Get the image dimensions.
  imageRect.size.height = CGImageGetHeight(image);
  imageRect.size.width = CGImageGetWidth(image);
  
  // Create a new image to receive the Quartz image data.
  newImage = [[NSImage alloc] initWithSize:imageRect.size];
  [newImage lockFocus];
  
  // Get the Quartz context and draw.
  imageContext = (CGContextRef)[[NSGraphicsContext currentContext]
                                graphicsPort];
  CGContextDrawImage(imageContext, *(CGRect*)&imageRect, image);
  [newImage unlockFocus];
  return [newImage autorelease];
}

#pragma mark Respresentation methods

- (NSData *)JPGRepresentationWithCompression:(float)compression
{
  NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:[self PNGRepresentationWithInterlaced:YES]];
  return [imageRep JPGRepresentationWithCompression:compression];
}

- (NSData *)PNGRepresentationWithInterlaced:(BOOL)interlaced
{
  NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:[self TIFFRepresentation]];
  return [imageRep PNGRepresentationWithInterlaced:interlaced];
}

- (NSData *)GIFRepresentationWithTransparency:(BOOL)transparency
{
  NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:[self PNGRepresentationWithInterlaced:YES]];
  return [imageRep GIFRepresentationWithTransparency:transparency];
}

#pragma mark Export methods - local

- (void)copyToClipboard
{
  NSPasteboard *pb = [NSPasteboard generalPasteboard];
  NSArray *pb_types = [NSArray arrayWithObjects:NSTIFFPboardType, nil];
  [pb declareTypes:pb_types owner:nil];
  [pb setData:[self TIFFRepresentation] forType:NSTIFFPboardType];
}

- (void)openWith:(NSString *)application
{
  NSString *path  = [NSTemporaryDirectory() stringByAppendingPathComponent:@"TIFFRepresentation.tiff"];
  if ([[self TIFFRepresentation] writeToFile:path atomically:YES]) {
    NSWorkspace *ws = [NSWorkspace sharedWorkspace];
    [ws openFile:path withApplication:application];
  }
}

- (void)openWith:(NSString *)application fileType:(NSString *)type option:(NSNumber *)option
{
  NSString *path;
  NSData *data;
  if ([type isEqualTo:@"JPGRepresentation"]) {
    path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ExportFile.jpg"];
    data = [self JPGRepresentationWithCompression:(float)[option floatValue]];
  } else   if ([type isEqualTo:@"PNGRepresentation"]) {
    path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ExportFile.png"];
    data = [self PNGRepresentationWithInterlaced:(BOOL)[option boolValue]];
  } else   if ([type isEqualTo:@"GIFRepresentation"]) {
    path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ExportFile.gif"];
    data = [self GIFRepresentationWithTransparency:(BOOL)[option boolValue]];
  } else {
    path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ExportFile.tiff"];
    data = [self TIFFRepresentation];
  }
  
  if ([data writeToFile:path atomically:YES]) {
    NSWorkspace *ws = [NSWorkspace sharedWorkspace];
    [ws openFile:path withApplication:application];
  }
}

-(BOOL)printImage {
  /* NOT FINISHED YET */
  NSPrintInfo *printInfo = [NSPrintInfo sharedPrintInfo];
  NSPrintOperation *printOp;
  NSRect r = NSMakeRect(0,0,[self size].width,[self size].height);
  NSImageView *imageView = [[[NSImageView alloc] initWithFrame:r] autorelease];
  [imageView setImage:self];
  [imageView beginDocument];

  printOp = [NSPrintOperation printOperationWithView:imageView printInfo:printInfo];

  [printOp setShowPanels:YES];
  [printOp runOperation];
  return YES;
}

#pragma mark Exporting to Internet

-(BOOL)uploadToImageShack
{
  [NSThread detachNewThreadSelector:@selector(uploadFormToImageShack) toTarget:[self JPGRepresentationWithCompression:0.9] withObject:nil];
  //[self uploadFormToImageShack];
  return YES;
}

#pragma mark Image editing

- (void)flipHorizontal
{
  NSImage *returnImage = [self copy];
  int width = [self size].width;
  int height = [self size].height;
   
  NSRect inRect = NSMakeRect(-width/2,-height/2,width,height);
  NSRect fromRect = NSMakeRect(0,0,width,height);

  [self lockFocus];
    [[NSGraphicsContext currentContext] saveGraphicsState];  
    NSAffineTransform *transform = [NSAffineTransform transform];
    [transform translateXBy:width/2 yBy:height/2];
    int flipByX = -1;
    int flipByY = 1;
    [transform scaleXBy:flipByX yBy:flipByY];
    [transform concat];
  
    [returnImage drawInRect:inRect 
          fromRect:fromRect 
           operation:NSCompositeCopy
          fraction:1.0];
  
    [[NSGraphicsContext currentContext] restoreGraphicsState];
  [self unlockFocus];
  [returnImage release];
  /*
  
  NSImage *returnImage = [[NSImage alloc] initWithSize:[self size]];
  int width = [self size].width;
  int height = [self size].height;
   
  NSRect inRect = NSMakeRect(-width/2,-height/2,width,height);
  NSRect fromRect = NSMakeRect(0,0,width,height);

  [returnImage lockFocus];
    [[NSGraphicsContext currentContext] saveGraphicsState];  
    NSAffineTransform *transform = [NSAffineTransform transform];
    [transform translateXBy:width/2 yBy:height/2];
    int flipByX = -1; //if (isFlippedHorizontal)  flipByX = -1;
    int flipByY = 1; //if (isFlippedVertical)    flipByY = -1;
    [transform scaleXBy:flipByX yBy:flipByY];
    //[transform rotateByDegrees:-rotationDegrees];
    [transform concat];
  
    [self drawInRect:inRect 
          fromRect:fromRect 
           operation:NSCompositeCopy 
          fraction:1.0];
  
    [[NSGraphicsContext currentContext] restoreGraphicsState];
  [returnImage unlockFocus];
  self = returnImage;
  [self openWith:@"DrawIt"];
  
  */

}

- (void)flipVertical
{
  NSImage *returnImage = [self copy];
  int width = [self size].width;
  int height = [self size].height;
   
  NSRect inRect = NSMakeRect(-width/2,-height/2,width,height);
  NSRect fromRect = NSMakeRect(0,0,width,height);

  [self lockFocus];
    [[NSGraphicsContext currentContext] saveGraphicsState];  
    NSAffineTransform *transform = [NSAffineTransform transform];
    [transform translateXBy:width/2 yBy:height/2];
    int flipByX = 1;
    int flipByY = -1;
    [transform scaleXBy:flipByX yBy:flipByY];
    [transform concat];
  
    [returnImage drawInRect:inRect 
          fromRect:fromRect 
           operation:NSCompositeCopy 
          fraction:1.0];
  
    [[NSGraphicsContext currentContext] restoreGraphicsState];
  [self unlockFocus];
  [returnImage release];
}

-(void)rotateClockwise {
    NSAffineTransform* xform = [NSAffineTransform transform];
  NSImage *oudImage = [self copy];
  [self setSize:NSMakeSize([oudImage size].height,[oudImage size].width)];
  [self lockFocus];
     [xform rotateByDegrees:-90];
     [xform concat];
     NSRect  r = NSMakeRect((-1*[oudImage size].width),0.0,[oudImage size].width,[oudImage size].height);
     NSRect r2 = NSMakeRect(0,0,[oudImage size].width,[oudImage size].height);
     [oudImage drawInRect:r fromRect:r2 operation:NSCompositeCopy fraction:1.0];
     [xform invert];
     [xform concat];
  [self unlockFocus];
  [oudImage release];
}

- (void)rotateAntiClockwise
{
  NSAffineTransform* xform = [NSAffineTransform transform];
  NSImage *oudImage = [self copy];
  [self setSize:NSMakeSize([oudImage size].height,[oudImage size].width)];
  [self lockFocus];
     [xform rotateByDegrees:90];
     [xform concat];
     NSRect r = NSMakeRect(0.0,(-1*[oudImage size].height),[oudImage size].width,[oudImage size].height);
     NSRect r2 = NSMakeRect(0,0,[oudImage size].width,[oudImage size].height);
     [oudImage drawInRect:r fromRect:r2 operation:NSCompositeCopy fraction:1.0];
     [xform invert];
     [xform concat];
  [self unlockFocus];
  [oudImage release];
}

@end

@implementation NSData (ImageShackUploadHelpers)

- (NSData*)generateFormData:(NSDictionary*)dict
{
  NSString* boundary = [NSString stringWithString:@"_insert_some_boundary_here_"];
  NSArray* keys = [dict allKeys];
  NSMutableData* result = [[NSMutableData alloc] initWithCapacity:100];
  
  int i;
  for (i = 0; i < [keys count]; i++) 
  {
    id value = [dict valueForKey: [keys objectAtIndex: i]];
    [result appendData:[[NSString stringWithFormat:@"--%@\n", boundary] dataUsingEncoding:NSASCIIStringEncoding]];
    if ( ([value class] == [NSString class]) || ([@"tmp" isKindOfClass:[value class]]))
    {
      [result appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\n\n", 
                           [keys objectAtIndex:i]] dataUsingEncoding:NSASCIIStringEncoding]];
      [result appendData:[[NSString stringWithFormat:@"%@",value] dataUsingEncoding:NSASCIIStringEncoding]];
    }
    else if ([value class] == [NSURL class] && [value isFileURL])
    {
      [result appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\n", [keys objectAtIndex:i], 
                           [[value path] lastPathComponent]] dataUsingEncoding:NSASCIIStringEncoding]];
      [result appendData:[[NSString stringWithString:@"Content-Type: application/octet-stream\n\n"] dataUsingEncoding:NSASCIIStringEncoding]];
      [result appendData:[NSData dataWithContentsOfFile:[value path]]];
    }
    
    [result appendData:[[NSString stringWithString:@"\n"] dataUsingEncoding:NSASCIIStringEncoding]];
  }
  [result appendData:[[NSString stringWithFormat:@"--%@--\n", boundary] dataUsingEncoding:NSASCIIStringEncoding]];
  
  return [result autorelease];
}

- (NSString *)stripXML:(NSString *)xml
{
  // knip alles weg achter '
  // <image_link>http://img159.imageshack.us/img159/1898/jelle2rl2.jpg</image_link>
  //
  
  NSArray *delenEen = [xml componentsSeparatedByString:@"<image_link>"];
  if ([delenEen count] == 1) return @"";
  NSString *goTwo = [delenEen objectAtIndex:1];
  delenEen = [goTwo componentsSeparatedByString:@"</image_link>"];
  return [delenEen objectAtIndex:0];
  
}

- (BOOL)uploadFormToImageShack
{
  NSAutoreleasePool *pool = [NSAutoreleasePool new];
  
  NSString *path  = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@32.jpg",NSUserName()]];
  [self writeToFile:path atomically:YES];
  
  NSMutableDictionary* post_dict = [[NSMutableDictionary alloc] init];
  [post_dict setValue:@"yes" forKey:@"xml"];
  [post_dict setObject:[NSURL fileURLWithPath:path] forKey:@"fileupload"];
  NSData* regData = [self generateFormData:post_dict];
  [post_dict release];
  
  
  //http://developer.mammoetsoftware.com/thing.php
  NSMutableURLRequest* post = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.imageshack.us/index.php"]];
  [post addValue: @"multipart/form-data; boundary=_insert_some_boundary_here_" forHTTPHeaderField: @"Content-Type"];
  [post setHTTPMethod: @"POST"];
  [post setHTTPBody:regData];
  NSURLResponse* response;
  NSError* error;
  
  NSData* result = [NSURLConnection sendSynchronousRequest:post returningResponse:&response error:&error];
  
  
  NSString *onlineRespons = [[[NSString alloc] initWithData:result encoding:NSASCIIStringEncoding] autorelease];
  
  NSString *onlineURL = [self stripXML:onlineRespons];
  
  
  [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:onlineURL]];
  
  [pool release];
  return YES;
}

@end


@implementation CIImage (CHCIImageAdditions)

- (NSData *)JPGRepresentationWithCompression:(float)compression
{
  return [[[[NSBitmapImageRep alloc] initWithCIImage:self] autorelease] JPGRepresentationWithCompression:compression];
}

- (NSData *)PNGRepresentationWithInterlaced:(BOOL)interlaced
{
  return [[[[NSBitmapImageRep alloc] initWithCIImage:self] autorelease] PNGRepresentationWithInterlaced:interlaced];
}

- (NSData *)GIFRepresentationWithTransparency:(BOOL)transparency
{
  return [[[[NSBitmapImageRep alloc] initWithCIImage:self] autorelease] GIFRepresentationWithTransparency:transparency];
}

-(NSData *)TIFFRepresentation
{
  return [[[[NSBitmapImageRep alloc] initWithCIImage:self] autorelease] TIFFRepresentation];
}

- (void)copyToClipboard
{
  NSPasteboard *pb = [NSPasteboard generalPasteboard];
  NSArray *pb_types = [NSArray arrayWithObjects:NSTIFFPboardType, nil];
  [pb declareTypes:pb_types owner:nil];
  [pb setData:[self TIFFRepresentation] forType:NSTIFFPboardType];
}

-(BOOL)uploadToImageShack
{
  [NSThread detachNewThreadSelector:@selector(uploadFormToImageShack) toTarget:[self JPGRepresentationWithCompression:0.9] withObject:nil];
  return YES;
}

@end

@implementation NSBitmapImageRep (CHBitmapRepAdditions)

- (NSData *)JPGRepresentationWithCompression:(float)compression
{
  [self setProperty:NSImageColorSyncProfileData withValue:nil];
  return [self representationUsingType:NSJPEGFileType
                                properties:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:compression] forKey:NSImageCompressionFactor]];
}

- (NSData *)PNGRepresentationWithInterlaced:(BOOL)interlaced
{
  [self setProperty:NSImageColorSyncProfileData withValue:nil];
  return [self representationUsingType:NSPNGFileType
                                properties:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:interlaced] forKey:NSImageInterlaced]];
}

- (NSData *)GIFRepresentationWithTransparency:(BOOL)transparency
{
  [self setProperty:NSImageColorSyncProfileData withValue:nil];
  return [self representationUsingType:NSGIFFileType
                                properties:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:transparency] forKey:NSImageDitherTransparency]];
}

@end